package device

import (
	"fmt"
	"iot/common"
	"strings"
	"sync"
	"time"
)

// SDeviceRealtimeInfo 设备实时数据
type SDeviceRealtimeInfo struct {
	DeviceIndex   string              `json:"device_index"`   // 所属设备索引
	IsOnline      bool                `json:"is_online"`      // 是否在线
	AlarmStatus   common.EAlarmStatus `json:"alarm_status"`   // 告警状态 (0:正常 1:警告 2:严重)
	StartupTime   time.Time           `json:"startup_time"`   // 本次启动时间
	SessionLength int64               `json:"session_length"` // 本次运行时⻓(秒)
}

type CDevice struct {
	//设备信息
	common.SDeviceInfo

	//设备实时数据
	SDeviceRealtimeInfo
	RtInfoMu sync.RWMutex

	//指令下发通道,容量为200
	InstrucQueue chan *SInstruction

	//设备权限
	PermissionMap map[string]common.EPermissionLevel

	//设备参数
	ArgumentGroup map[string][]*CArgument
	ArgumentMap   map[string]*CArgument
	ArgumentList  []CArgument
}

func (device *CDevice) Info() *common.SDeviceInfo {
	return &device.SDeviceInfo
}

func (device *CDevice) RtInfo() SDeviceRealtimeInfo {
	device.RtInfoMu.RLock()
	defer device.RtInfoMu.RUnlock()
	return device.SDeviceRealtimeInfo
}

func (device *CDevice) SetRtInfo(rtInfo SDeviceRealtimeInfo) {
	device.RtInfoMu.Lock()
	defer device.RtInfoMu.Unlock()
	device.SDeviceRealtimeInfo = rtInfo
}

// PopInstruct 尝试读取设备指令
func (device *CDevice) PopInstruct() []*SInstruction {
	var cmds []*SInstruction
	for {
		select {
		case inst := <-device.InstrucQueue:
			cmds = append(cmds, inst)
		default:
			return cmds
		}
	}
}

// PushInstruction 发送指令到设备指令通道
func (device *CDevice) PushInstruction(inst *SInstruction, timeout time.Duration) bool {
	select {
	case device.InstrucQueue <- inst:
		return true
	case <-time.After(timeout):
		return false
	}
}

// Argument 根据索引获取参数指针
func (device *CDevice) Argument(idx string) *CArgument {
	if arg, exists := device.ArgumentMap[idx]; exists {
		return arg
	}
	return nil
}

// Arguments 读取所有参数指针
func (device *CDevice) Arguments() []*CArgument {
	results := make([]*CArgument, len(device.ArgumentList))
	for i := range device.ArgumentList {
		results[i] = &device.ArgumentList[i]
	}
	return results
}

// ArgumentByGroup 获取指定参数组中的所有参数
func (device *CDevice) ArgumentByGroup(groupName string) []*CArgument {
	if group, exists := device.ArgumentGroup[groupName]; exists {
		return group
	}
	return nil
}

// RtArg 通过索引读取参数实时数据
func (device *CDevice) RtArg(idx string) SRtValue {
	arg, exists := device.ArgumentMap[idx]
	if !exists {
		return SRtValue{}
	}
	return arg.Rt()
}

// SetRtArg 设置实时数据
func (device *CDevice) SetRtArg(value SRtValue) {
	arg, exists := device.ArgumentMap[value.ArgIndex]
	if !exists {
		return
	}
	arg.SetRt(value)
}

func (device *CDevice) Show() string {
	rtInfo := device.RtInfo()
	var buf strings.Builder
	buf.WriteString(fmt.Sprintf("=================== %s ===================\n", device.Name))
	buf.WriteString(fmt.Sprintf("描述: %s\n", device.Descr))
	buf.WriteString(fmt.Sprintf("创建时间: %s\n", time.Unix(device.CreateTime, 0).Format("2006-01-02 15:04:05")))
	buf.WriteString(fmt.Sprintf("设备型号: %s\n", device.Model))
	buf.WriteString(fmt.Sprintf("生产厂家: %s\n", device.Manufacturer))
	buf.WriteString(fmt.Sprintf("序列号: %s\n", device.SerialNumber))
	buf.WriteString(fmt.Sprintf("软件版本: %s\n", device.SoftwareVersion))
	buf.WriteString(fmt.Sprintf("硬件版本: %s\n", device.HardwareVersion))
	buf.WriteString(fmt.Sprintf("安装位置: %s\n", device.InstallationSite))
	historyStatus := "禁用"
	if device.IsEnableHistory == common.Enable {
		historyStatus = "启用"
	}
	buf.WriteString(fmt.Sprintf("历史存储: %s\n", historyStatus))

	if !rtInfo.IsOnline {
		lastOnline := time.Unix(device.LastOnlineTime, 0).Format("2006-01-02 15:04:05")
		buf.WriteString(fmt.Sprintf("在线状态: %s (最后在线: %s)\n", "离线", lastOnline))
	} else {
		buf.WriteString(fmt.Sprintf("实时数据:\n"))
		alarmStatus := "正常"
		switch rtInfo.AlarmStatus {
		case common.EAlarmStatusWarning:
			alarmStatus = "警告"
		case common.EAlarmStatusCritical:
			alarmStatus = "严重"
		}
		buf.WriteString(fmt.Sprintf("    在线状态: %s (最后在线: %s)\n", "在线", time.Now().Format("2006-01-02 15:04:05")))
		buf.WriteString(fmt.Sprintf("    告警状态: %s\n", alarmStatus))
		buf.WriteString(fmt.Sprintf("    启动时间: %s\n", rtInfo.StartupTime.Format("2006-01-02 15:04:05")))
		buf.WriteString(fmt.Sprintf("    运行时长: %d 小时, %d 分钟\n", rtInfo.SessionLength/(3600), (rtInfo.SessionLength%(3600))/60))
	}

	buf.WriteString(fmt.Sprintf("分组信息:\n"))
	for group, _ := range device.ArgumentGroup {
		buf.WriteString(fmt.Sprintf("    %s:参数数量 %d\n", group, len(device.ArgumentGroup[group])))
	}

	buf.WriteString(fmt.Sprintf("设备权限:\n"))
	for us, _ := range device.PermissionMap {
		var permission string
		switch device.PermissionMap[us] {
		case common.EPermissionLevelReadOnly:
			permission = "只读"
		case common.EPermissionLevelReadWrite:
			permission = "读写"
		case common.EPermissionLevelAdmin:
			permission = "可管理"
		default:
			permission = "只读"
		}
		buf.WriteString(fmt.Sprintf("    %s: %d\n", us, permission))
	}

	return buf.String()
}

func (device *CDevice) ShowGroup(gp string, isRt bool) string {
	_, exits := device.ArgumentGroup[gp]
	if !exits {
		return ""
	}

	var buf strings.Builder
	if isRt {
		buf.WriteString(fmt.Sprintf("参数  |  实时值  |  数据源  |  质量码  |  时标\n"))
	} else {
		buf.WriteString(fmt.Sprintf("********************** %s **********************\n", gp))
	}

	for _, arg := range device.ArgumentGroup[gp] {
		buf.WriteString(arg.Show(isRt))
	}
	return buf.String()
}
